﻿using GComp.Apps.EasyStock.Common;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace GComp.Apps.EasyStock.DataModel.Common {
    public class StockQuote : BindableBase {
        public StockQuote(string symbol) {
            _symbol = symbol;
        }

        private string _symbol = string.Empty;
        public string Symbol {
            get { return _symbol; }
        }

        private string _name = string.Empty;
        public string Name {
            get { return _name; }
            set { SetProperty(ref _name, value); }
        }

        private decimal _previousClose;
        public decimal PreviousClose {
            get { return _previousClose; }
            set { SetProperty(ref _previousClose, value); }
        }

        private decimal _open;
        public decimal Open {
            get { return _open; }
            set { SetProperty(ref _open, value); }
        }

        private decimal _lastPrice;
        public decimal LastPrice {
            get { return _lastPrice; }
            set { SetProperty(ref _lastPrice, value); }
        }

        private decimal _daysLow;
        public decimal DaysLow {
            get { return _daysLow; }
            set {
                if (SetProperty(ref _daysLow, value))
                    OnPropertyChanged("LowHighString");
            }
        }

        private decimal _daysHigh;
        public decimal DaysHigh {
            get { return _daysHigh; }
            set {
                if (SetProperty(ref _daysHigh, value))
                    OnPropertyChanged("LowHighString");
            }
        }

        public string LowHighString {
            get { return string.Format("{0} - {1}", DaysLow, DaysHigh); }
        }

        private decimal _change;
        public decimal Change {
            get { return _change; }
            set {
                if (SetProperty(ref _change, value))
                    OnPropertyChanged("ChangeString");
            }
        }

        private double _changePercent;
        public double ChangePercent {
            get { return _changePercent; }
            set {
                if (SetProperty(ref _changePercent, value))
                    OnPropertyChanged("ChangeString");
            }
        }

        public string ChangeString {
            get { return string.Format("{0:+0.00;-0.00;±0} ({1:+0.00;-0.00;±0} %)", Change, ChangePercent); }
        }

        private List<Tuple<DateTime, decimal>> _history = new List<Tuple<DateTime, decimal>>();
        public List<Tuple<DateTime, decimal>> History {
            get { return _history; }
            set { SetProperty(ref _history, value); }
        }

        private void FillData(XElement xml) {
            Name = xml.Element("Name").Value;
            string strTmp = xml.Element("ErrorIndicationreturnedforsymbolchangedinvalid").Value;
            if (string.IsNullOrEmpty(strTmp)) {
                decimal decTmp;
                strTmp = xml.Element("PreviousClose").Value;
                if (decimal.TryParse(strTmp, NumberStyles.Any, CultureInfo.InvariantCulture, out decTmp))
                    PreviousClose = decTmp;
                strTmp = xml.Element("Open").Value;
                if (decimal.TryParse(strTmp, NumberStyles.Any, CultureInfo.InvariantCulture, out decTmp))
                    Open = decTmp;
                strTmp = xml.Element("LastTradePriceOnly").Value;
                if (decimal.TryParse(strTmp, NumberStyles.Any, CultureInfo.InvariantCulture, out decTmp))
                    LastPrice = decTmp;
                strTmp = xml.Element("DaysLow").Value;
                if (decimal.TryParse(strTmp, NumberStyles.Any, CultureInfo.InvariantCulture, out decTmp))
                    DaysLow = decTmp;
                strTmp = xml.Element("DaysHigh").Value;
                if (decimal.TryParse(strTmp, NumberStyles.Any, CultureInfo.InvariantCulture, out decTmp))
                    DaysHigh = decTmp;
                strTmp = xml.Element("Change").Value;
                if (decimal.TryParse(strTmp, NumberStyles.Any, CultureInfo.InvariantCulture, out decTmp))
                    Change = decTmp;
                double dblTmp;
                strTmp = xml.Element("PercentChange").Value;
                if (double.TryParse(strTmp.Substring(0, strTmp.Length - 1), NumberStyles.Any, CultureInfo.InvariantCulture, out dblTmp))
                    ChangePercent = dblTmp;
            } else {
                Name = strTmp;
            }
        }

        public static StockQuote FromXml(XElement xml) {
            string symbol = xml.Element("Symbol").Value;
            StockQuote q = new StockQuote(symbol);
            q.FillData(xml);
            return q;
        }

        public async Task<bool> LoadData() {
            QuoteQuery query = new QuoteQuery(Symbol);
            XDocument doc = await query.GetXmlAnswerAsync();
            XElement xml = doc.Descendants("quote").FirstOrDefault();
            if (xml != null) {
                FillData(xml);
                return true;
            }
            return false;
        }

        public async void LoadHistory(DateTime start, DateTime end) {
            HistoryQuery query = new HistoryQuery(Symbol, start, end);
            History = await query.GetAnswerAsync();
        }

        public override string ToString() {
            return string.Format("{0} ({1})", Symbol, Name);
        }

    }
}
